
#ifndef _TTG_DEVICES_CPU_CPU_
#define _TTG_DEVICES_CPU_CPU_
#include "Common/Definitions.h"

#include "Runtime.Low/Devices/Devices.h"
#include "Runtime.Low/Devices/IdManager.h"
//<fix_me>
#include "Runtime.Low/Services/DeviceAnalyzer/CPUAnalyzer.h"
//</fix_me>

namespace ttg
{
	namespace devices
	{
		//Definition of CPU device (that always exists and available).
		class CPU :public Device
		{
			private:
				static CPU *ref;

				static inline void safeInit()
				{
					if (ref == NULL)
						ref = new CPU();
				}
				//Acquires ID and registers device.
				inline CPU()
					:Device("CPU",
						    ttg_internal::devices::IdManager::getRef()->generateDeviceID())
				{ /*nothing*/ }
			public:
				//Returns instance of CPU.
				static inline CPU *getRef()
				{ safeInit(); return ref; }
			//Defenition of the known APIs.

				//Classical x86-compatible architecture (without SSE and other extensions).
				//It's always available.
				class x86 :public Api
				{
					private:
						static x86 *ref;

						static inline void safeInit()
						{
							if (ref == NULL)
								ref = new x86();
						}
						//Creates and registers default API for CPU.
						inline x86()
							:Api("x86",
								 ttg_internal::devices::IdManager::getRef()->generateApiID(CPU::getRef()->getID()),
								 CPU::getRef())
						{ /*nothing*/ }
					public:
						//Returns true, if API is available on this machine.
						virtual bool isAvailable()
						{ return true; }
						//Returns true, if additional CPU-thread is requred.
						//It means, that corresponded task will use CPU-thread as well as this device.
						virtual bool isAccelerator()
						{ return true; }
						//Returns count of tasks, that can be executed simultaneously via this API.
						virtual size_t getConcurrencyLevel()
						{ return ttg::services::CPUAnalyzer::determineCoreCount(); }
						//Returns instance of x86 API.
						static inline x86 *getRef()
						{ safeInit(); return ref; }
						//Returns logical x86-compatible CPU.
						static inline LogicalDevice getType()
						{ return LogicalDevice(CPU::getRef()->getID(), x86::getRef()->getID()); }
				};
		};
	}
}

#endif
